package com.edu.buservice.biz.handler.strategy;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.edu.buservice.biz.TenantManger;
import com.edu.buservice.biz.UserManger;
import com.edu.buservice.biz.config.CommonConfig;
import com.edu.buservice.biz.enums.DomainEnum;
import com.edu.buservice.biz.model.RequestContext;
import com.edu.buservice.biz.model.dto.TenantInfoDTO;
import com.edu.buservice.biz.model.dto.UpdateUserInfoDTO;
import com.edu.buservice.dal.model.SysUsers;
import com.edu.buservice.facade.constants.SessionKeyConstant;
import com.edu.buservice.util.model.TenantContext;
import com.edu.buservice.util.model.TenantUtil;
import com.edu.buservice.util.model.UserInfoDTO;
import com.edu.buservice.util.model.enums.ErrorCodeEnum;
import com.edu.buservice.util.model.error.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @program: KQAIA
 * @description:
 * @author: 无恙
 * @create: 2025-03-07 22:32
 **/

@Slf4j
public abstract class AbstractLoginImpl implements LoginStrategy {

	@Autowired
	private UserManger userManger;

	@Autowired
	private CommonConfig commonConfig;

	@Autowired
	private TenantManger tenantManger;

	@Override
	public String doProcess(RequestContext context) {

		try {

			// 前置处理
			preLogin(context);

			//用户聊天侧不需要处理租户信息
			if(DomainEnum.USER.getDomain().equals(context.getDomain().getDomain())){
				//默认设置为用户聊天侧的租户ID
				context.setTenantId(commonConfig.getUserTenantId());
			}else if( DomainEnum.ADMIN.getDomain().equals(context.getDomain().getDomain())) {
				context.setTenantId(commonConfig.getAdminTenantId());
			}else {
				doProcessTenant(context);
			}

			//设置当前租户ID
			TenantUtil.setCurrentTenantId(context.getTenantId());

			//处理登录
			doLogin(context);

			//加载会话信息
			loadSession(context);

			//更新登录信息
			updateLoginInfo(context);


		}catch (BizException e){
			log.error("登录异常", e);
			StpUtil.logout();
			throw e;
		}catch (Exception e){
			log.error("登录异常", e);
			StpUtil.logout();
			throw new BizException(ErrorCodeEnum.AUTH_ERROR);
		}


		return context.getRedirect();


	}

	protected void doProcessTenant(RequestContext context) {
		// 判断是否选择了租户
		if (StrUtil.isNotEmpty(context.getTenantId())) {
			return;
		}

		// 查询用户信息
		List<SysUsers> usersList = userManger.getUserInfoWithoutTenant(context.getUserId(), context.getPhone());

		if (CollectionUtil.isEmpty(usersList)) {
			throw new BizException(ErrorCodeEnum.USER_NOT_FOUND);
		}

		// 如果存在一个用户信息，则直接使用这个租户
		if (usersList.size() == 1) {
			context.setTenantId(usersList.get(0).getTenantId());
			return;
		}

		// 如果存在多个用户信息，默认选择最近登录的租户
		SysUsers recentUser = usersList.stream()
				.max(Comparator.comparing(
						SysUsers::getLastLoginTime,
						Comparator.nullsLast(Comparator.naturalOrder())
				))
				.orElseThrow(() -> new BizException(ErrorCodeEnum.USER_NOT_FOUND));


		context.setTenantId(recentUser.getTenantId());


	}

	//加载会话信息
	protected void loadSession(RequestContext context) {
		// 获取用户信息
		UserInfoDTO userInfoDTO = userManger.getUserInfoById(context.getUserId());


		if(Objects.isNull(userInfoDTO)){
			throw new BizException(ErrorCodeEnum.USER_NOT_FOUND);
		}

		TenantInfoDTO tenantInfo = tenantManger.getTenantInfoByTenantId(context.getTenantId());

		if(Objects.isNull(tenantInfo)){
			throw new BizException(ErrorCodeEnum.TENANT_NOT_FOUND);
		}



		TenantContext tenantContext = new TenantContext();
		tenantContext.setTenantId(context.getTenantId());
		tenantContext.setTenantName(tenantInfo.getName());
		tenantContext.setUserId(context.getUserId());
		tenantContext.setUserInfo(userInfoDTO);
		tenantContext.setRole(userInfoDTO.getRole());
		tenantContext.setPermissions(userInfoDTO.getPermissions());
		TenantUtil.init(tenantContext);

		userInfoDTO.setTenantId(context.getTenantId());

		StpUtil.getSession().set(SessionKeyConstant.USER_INFO, userInfoDTO);

	}

	private void updateLoginInfo(RequestContext context) {
		// 更新登录信息

		UpdateUserInfoDTO updateUserInfoDTO = new UpdateUserInfoDTO();
		updateUserInfoDTO.setUserId(context.getUserId());

		//更新最后登录时间
		updateUserInfoDTO.setLastLoginTime(new Date());

		//更新最后登录Ip
		updateUserInfoDTO.setLastLoginIp(context.getIp());
		userManger.updateUser(updateUserInfoDTO);
	}



	@Override
	public void preLogin(RequestContext context) {

	}

	@Override
	public void doLogin(RequestContext context) {

	}




}
